package org.aman.generator.mapper;

import static org.mybatis.generator.internal.util.JavaBeansUtil.getCamelCaseString;
import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.aman.generator.plugin.AmanPluginConfig;
import org.aman.generator.util.XmlMapperUtil;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.codegen.mybatis3.xmlmapper.XMLMapperGenerator;
import org.mybatis.generator.exception.XMLParserException;

/**
 * @desc <p></p>
 * @author DaiJiangGuo
 * @date 2015年5月12日下午4:32:57
 */
public class ExtendsXmlMapperGenerator extends XMLMapperGenerator{
    private AmanPluginConfig apc;
    public ExtendsXmlMapperGenerator(AmanPluginConfig apc) {
        super();
        this.apc = apc;
        this.setContext(apc.context);
        this.setIntrospectedTable(apc.introspectedTable);
        initialized();
    }

    public void initialized() {

    }

    protected XmlElement getBaseColumnListElement() {
        XmlElement answer = new XmlElement("include"); //$NON-NLS-1$
        answer.addAttribute(new Attribute("refid", introspectedTable.getBaseColumnListId()));
        return answer;
    }

    protected XmlElement getBlobColumnListElement() {
        XmlElement answer = new XmlElement("include"); //$NON-NLS-1$
        answer.addAttribute(new Attribute("refid", //$NON-NLS-1$
                introspectedTable.getBlobColumnListId()));
        return answer;
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 下午5:21:09
     * @param document
     * @param string
     */
    public void addQueryByMapMethod(Document document, String name) {
        XmlElement answer = new XmlElement("select"); //$NON-NLS-1$

        answer.addAttribute(new Attribute("id", name)); //$NON-NLS-1$

        if (introspectedTable.getRules().generateResultMapWithBLOBs()) {
            answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                    introspectedTable.getResultMapWithBLOBsId()));
        } else {
            answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                    introspectedTable.getBaseResultMapId()));
        }

        String parameterType = "map";

        answer.addAttribute(new Attribute("parameterType", //$NON-NLS-1$
                parameterType));

        context.getCommentGenerator().addComment(answer);

        StringBuilder sb = new StringBuilder();
        sb.append("select "); //$NON-NLS-1$

        if (stringHasValue(introspectedTable
                .getSelectByPrimaryKeyQueryId())) {
            sb.append('\'');
            sb.append(introspectedTable.getSelectByPrimaryKeyQueryId());
            sb.append("' as QUERYID,"); //$NON-NLS-1$
        }
        answer.addElement(new TextElement(sb.toString()));
        answer.addElement(getBaseColumnListElement());
        if (introspectedTable.hasBLOBColumns()) {
            answer.addElement(new TextElement(",")); //$NON-NLS-1$
            answer.addElement(getBlobColumnListElement());
        }

        sb.setLength(0);
        sb.append("from "); //$NON-NLS-1$
        sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime());
        answer.addElement(new TextElement(sb.toString()));

        //=============
        XmlElement dynamicElement = new XmlElement("where"); //$NON-NLS-1$
        answer.addElement(dynamicElement);
        for (IntrospectedColumn introspectedColumn : introspectedTable.getNonPrimaryKeyColumns()) {
            XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
            sb.setLength(0);
            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null"); //$NON-NLS-1$
            isNotNullElement.addAttribute(new Attribute("test", sb.toString())); //$NON-NLS-1$
            dynamicElement.addElement(isNotNullElement);

            sb.setLength(0);
            sb.append(" and ");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            sb.append(" = "); //$NON-NLS-1$
            sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
            sb.append(' ');

            isNotNullElement.addElement(new TextElement(sb.toString()));
        }
        //==============

        document.getRootElement().addElement(answer);

    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 下午5:21:17
     * @param document
     * @param string
     */
    public void addQueryByEntityMethod(Document document, String name) {
        XmlElement answer = new XmlElement("select"); //$NON-NLS-1$

        answer.addAttribute(new Attribute("id", name)); //$NON-NLS-1$

        if (introspectedTable.getRules().generateResultMapWithBLOBs()) {
            answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                    introspectedTable.getResultMapWithBLOBsId()));
        } else {
            answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                    introspectedTable.getBaseResultMapId()));
        }

        FullyQualifiedJavaType parameterType = introspectedTable.getRules()
                .calculateAllFieldsClass();

        answer.addAttribute(new Attribute("parameterType", //$NON-NLS-1$
                parameterType.getFullyQualifiedName()));

        context.getCommentGenerator().addComment(answer);

        StringBuilder sb = new StringBuilder();
        sb.append("select "); //$NON-NLS-1$

        if (stringHasValue(introspectedTable
                .getSelectByPrimaryKeyQueryId())) {
            sb.append('\'');
            sb.append(introspectedTable.getSelectByPrimaryKeyQueryId());
            sb.append("' as QUERYID,"); //$NON-NLS-1$
        }
        answer.addElement(new TextElement(sb.toString()));
        answer.addElement(getBaseColumnListElement());
        if (introspectedTable.hasBLOBColumns()) {
            answer.addElement(new TextElement(",")); //$NON-NLS-1$
            answer.addElement(getBlobColumnListElement());
        }

        sb.setLength(0);
        sb.append("from "); //$NON-NLS-1$
        sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime());
        answer.addElement(new TextElement(sb.toString()));

        //=============
        XmlElement dynamicElement = new XmlElement("where"); //$NON-NLS-1$
        answer.addElement(dynamicElement);
        for (IntrospectedColumn introspectedColumn : introspectedTable.getNonPrimaryKeyColumns()) {
            XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
            sb.setLength(0);
            sb.append(introspectedColumn.getJavaProperty());
            sb.append(" != null"); //$NON-NLS-1$
            isNotNullElement.addAttribute(new Attribute("test", sb.toString())); //$NON-NLS-1$
            dynamicElement.addElement(isNotNullElement);

            sb.setLength(0);
            sb.append(" and ");
            sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
            sb.append(" = "); //$NON-NLS-1$
            sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
            sb.append(' ');

            isNotNullElement.addElement(new TextElement(sb.toString()));
        }
        //==============

        document.getRootElement().addElement(answer);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月12日 下午5:21:24
     * @param document
     * @param string
     */
    public void addQueryByPagerMethod(Document document, String name) {
        if(apc.serviceMethod_gen_queryByPager){
            XmlElement answer = new XmlElement("select"); //$NON-NLS-1$

            answer.addAttribute(new Attribute("id", name)); //$NON-NLS-1$

            if (introspectedTable.getRules().generateResultMapWithBLOBs()) {
                answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                        introspectedTable.getResultMapWithBLOBsId()));
            } else {
                answer.addAttribute(new Attribute("resultMap", //$NON-NLS-1$
                        introspectedTable.getBaseResultMapId()));
            }

            answer.addAttribute(new Attribute("parameterType", //$NON-NLS-1$
                    apc.pagerType.getPackageName()+"."+apc.pagerType.getShortName()));

            context.getCommentGenerator().addComment(answer);

            StringBuilder sb = new StringBuilder();
            sb.append("select "); //$NON-NLS-1$

            if (stringHasValue(introspectedTable
                    .getSelectByPrimaryKeyQueryId())) {
                sb.append('\'');
                sb.append(introspectedTable.getSelectByPrimaryKeyQueryId());
                sb.append("' as QUERYID,"); //$NON-NLS-1$
            }
            answer.addElement(new TextElement(sb.toString()));
            answer.addElement(getBaseColumnListElement());
            if (introspectedTable.hasBLOBColumns()) {
                answer.addElement(new TextElement(",")); //$NON-NLS-1$
                answer.addElement(getBlobColumnListElement());
            }

            sb.setLength(0);
            sb.append("from "); //$NON-NLS-1$
            sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime());
            answer.addElement(new TextElement(sb.toString()));

            //=============
            XmlElement dynamicElement = new XmlElement("where"); //$NON-NLS-1$
            answer.addElement(dynamicElement);
            for (IntrospectedColumn introspectedColumn : introspectedTable.getNonPrimaryKeyColumns()) {
                XmlElement isNotNullElement = new XmlElement("if"); //$NON-NLS-1$
                sb.setLength(0);
                sb.append(apc.pagerPref + introspectedColumn.getJavaProperty());
                sb.append(" != null"); //$NON-NLS-1$
                isNotNullElement.addAttribute(new Attribute("test", sb.toString())); //$NON-NLS-1$
                dynamicElement.addElement(isNotNullElement);

                sb.setLength(0);
                sb.append(" and ");
                sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
                sb.append(" = "); //$NON-NLS-1$
                sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn, apc.pagerPref));
                sb.append(' ');

                isNotNullElement.addElement(new TextElement(sb.toString()));
            }
            //==============

            document.getRootElement().addElement(answer);
        }
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月15日 下午6:48:42
     * @param add
     * @param targetFile
     * @param sqlMap
     * @param introspectedTable
     * @throws ParserConfigurationException
     * @throws XMLParserException
     * @throws IOException
     */
    public void addColumns(List<IntrospectedColumn> needAddCols, File targetFile, GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        XmlMapperUtil.mergedAddColSource(needAddCols, targetFile, sqlMap, introspectedTable);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月15日 下午6:48:50
     * @param needUpdCols
     * @param targetFile
     * @param sqlMap
     * @param introspectedTable
     */
    public void updColumns(List<IntrospectedColumn> needUpdCols, File targetFile, GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        Map<String, IntrospectedColumn> updMap = new HashMap<String, IntrospectedColumn>();
        for(IntrospectedColumn col : needUpdCols){
            updMap.put(col.getActualColumnName(), col);
        }
        XmlMapperUtil.mergedUpdColSource(updMap, targetFile, sqlMap, introspectedTable);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月15日 下午6:48:57
     * @param needDelFields
     * @param targetFile
     * @param sqlMap
     * @param introspectedTable
     */
    public void delColumns(List<IntrospectedColumn> needDelFields, File targetFile, GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        XmlMapperUtil.mergedDelColSource(needDelFields, targetFile, sqlMap, introspectedTable);
    }

    /**
     * @author DaiJiangGuo
     * @data 2015年5月15日 下午6:49:01
     * @param targetFile
     * @param sqlMap
     * @param introspectedTable
     * @return
     */
    public boolean matcherUpdColums(File targetFile, GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        XmlMapperUtil.mergedColSource(targetFile, sqlMap, introspectedTable);
        return false;
    }

}

